using System;
using System.Collections.Generic;
using System.Reflection;
using System.Text;
using SpoonCore2.Client;
using SpoonCore2.Message.Header;
using SpoonCore2.Service;
using System.IO;

namespace SpoonCore2.Message.Header
{
	class MessageOptionManager
	{
		private readonly ServiceManager _manager;
		private readonly SortedList<byte, Type> _optionTypes = new SortedList<byte, Type>();
		private readonly SortedList<byte, IMessageOptionHandler> _handler = new SortedList<byte, IMessageOptionHandler>();
		
		public MessageOptionManager(ServiceManager manager)
		{
			_manager = manager;

			Init();
		}

		private void Init()
		{
			foreach (Type type in Assembly.GetCallingAssembly().GetTypes())
			{
				foreach (Type interf in type.GetInterfaces())
				{
					if (interf == typeof(IMessageOptionHandler) && !type.IsAbstract && !type.IsInterface) Register((IMessageOptionHandler)Activator.CreateInstance(type));
				}
			}
		}

		private void Register(IMessageOptionHandler handler)
		{
			if (!_handler.ContainsKey(handler.Option.Id))
			{
				_handler.Add(handler.Option.Id, handler);
				if (!_optionTypes.ContainsKey(handler.Option.Id)) _optionTypes.Add(handler.Option.Id, handler.Option.GetType());
				handler.SetManager(_manager);
			}
		}

		public void GetBytes(BinaryWriter bw, IMessage message)
		{
			bw.Write(message.Options.Count);
			foreach (IMessageOption option in message.Options)
			{
				bw.Write(option.Id);
				option.GetBytes(bw);
			}
		}

		public IList<IMessageOption> SetBytes(BinaryReader br)
		{
			int count = br.ReadInt32();
			IList<IMessageOption> res = new List<IMessageOption>();
			while (count > 0)
			{
				byte id = br.ReadByte();
				if (_optionTypes.ContainsKey(id))
				{
					IMessageOption tmp = (IMessageOption)Activator.CreateInstance(_optionTypes[id]);
					tmp.SetBytes(br);
					res.Add(tmp);
				}
			}
			return res;
		}
	}
}